package com.srt.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.srt.enums.CategoryEnum;
import com.srt.enums.SystypeEnum;
import com.srt.mapper.VedioCutoffMapper;
import com.srt.model.Catalog;
import com.srt.model.VedioCutoff;
import com.srt.util.service.CommonService;
import com.srt.vo.VedioCutoffExportVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author rd06
 * @since 2021-05-11
 */
@Slf4j
@Service
public class VedioCutoffService extends CommonService<VedioCutoffMapper, VedioCutoff> {
    @Autowired
    private CatalogService catalogService;

    /**
     * 根据项目获取截取时间情况
     *
     * @param cataLogId
     * @return
     */
    public List<VedioCutoff> queryListByCataLogId(Long cataLogId) {
        return this.lambdaQuery().eq(VedioCutoff::getCatalogId, cataLogId).list();
    }

    /**
     * 保存截取的数据先删除后添加
     */
    @Transactional
    public int save(List<VedioCutoff> vedioCutoffList, Long catalogId) {
        if (CollUtil.isEmpty(vedioCutoffList)) {
            return 0;
        }
        //删除
        int num = this.getBaseMapper().delete(new LambdaQueryWrapper<VedioCutoff>().eq(VedioCutoff::getCatalogId, catalogId));
        log.info("【保存】catalogId:{},删除了{}个", catalogId, num);
        vedioCutoffList = vedioCutoffList.stream().filter(item -> item.getStartTime() != null && item.getEndTime() != null).collect(Collectors.toList());;
        for (VedioCutoff item : vedioCutoffList) {
            item.setCatalogId(catalogId);
        }
        saveBatch(vedioCutoffList);
        return 1;
    }

    /**
     * 导出
     *
     * @param vedioCutoffExportVO
     */
    public void export(VedioCutoffExportVO vedioCutoffExportVO, HttpServletResponse response) throws IOException {
        Long catalogId = vedioCutoffExportVO.getCatalogId();
        String videoName = vedioCutoffExportVO.getVideoName();
        String sysType = vedioCutoffExportVO.getSysType();
        Catalog catalog = catalogService.getById(catalogId);
        if (ObjectUtil.isNull(catalog)) {
            return;
        }
        //获取所有的截取时间
        List<VedioCutoff> vedioCutoffList = lambdaQuery().eq(VedioCutoff::getCatalogId, catalogId).list();
        String path3 = System.getProperty("user.dir");
        String dirPath = path3 + File.separator + catalogId;
        creatFile(CategoryEnum.WORSHIP, vedioCutoffList, dirPath);
        creatFile(CategoryEnum.PRAY, vedioCutoffList, dirPath);
        creatFile(CategoryEnum.REVIEW, vedioCutoffList, dirPath);
        creatFile(CategoryEnum.TRAILER, vedioCutoffList, dirPath);
        creatFile(CategoryEnum.PART, vedioCutoffList, dirPath);
        StringBuilder sb = new StringBuilder();
        List<String> tsList = ListUtil.list(false);
        for (VedioCutoff vedioCutoff : vedioCutoffList) {
            String tsName = vedioCutoff.getName() + "_clip.ts";
            sb.append("ffmpeg -ss ").append(vedioCutoff.getStartTime()).append(" -to ").append(vedioCutoff.getEndTime()).append(" -i \"")
                    .append(videoName).append("\" -c:v copy -bsf:v h264_mp4toannexb -f mpegts -acodec copy \"")
                    .append(tsName).append("\"\r\n");
            tsList.add(tsName);
        }
        sb.append("\r\n").append("\r\n").append("\r\n");

        List<String> mp4List = ListUtil.list(false);
        for (VedioCutoff vedioCutoff : vedioCutoffList) {
            String mp4name = vedioCutoff.getName() + "_clip.mp4";
            sb.append("ffmpeg -f concat -safe 0 -i ").append(vedioCutoff.getName()).append(".txt -c:v copy \"").append(mp4name).append("\"\r\n");
            mp4List.add(mp4name);
        }
        sb.append("\r\n").append("\r\n").append("\r\n");

        for (VedioCutoff vedioCutoff : vedioCutoffList) {
            String mp4ClipName = vedioCutoff.getName() + "_clip.mp4";
            String mp4name = vedioCutoff.getName() + ".mp4";
            sb.append("ffmpeg -i \"").append(mp4ClipName).append("\" -vcodec copy -bsf:v h264_mp4toannexb \"").append(mp4name).append("\"\r\n");
        }
        sb.append("\r\n").append("\r\n").append("\r\n");


        delFile(sb, sysType, tsList);
        sb.append("\r\n").append("\r\n").append("\r\n");
        delFile(sb, sysType, mp4List);


        String zhixingName = SystypeEnum.WIN.name().equals(sysType) ? "fanyi.bat" : "fanyi.sh";
        File file = new File(dirPath + File.separator + zhixingName);
        try (FileOutputStream outputStream = new FileOutputStream(file)) {
            outputStream.write(sb.toString().getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            log.error("生成sh/bat 文件异常了");
        }

        //打包文件生成zip进行下载
        try (FileInputStream fileInputStream = new FileInputStream(ZipUtil.zip(dirPath)); OutputStream outputStream = response.getOutputStream()) {
            int num;
            byte[] bytes = new byte[1024];
            while ((num = fileInputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, num);
            }
        } catch (IOException e) {
            log.error("下载异常了", e);
        }
    }

    /**
     * 删除文件
     *
     * @param fileList
     * @return
     */
    private void delFile(StringBuilder sb, String sysType, List<String> fileList) {
        for (String s : fileList) {
            if ("WIN".equals(sysType)) {
                sb.append("del ");
            } else {
                sb.append("rm ");
            }
            sb.append(s).append("\r\n");
        }

        if ("WIN".equals(sysType)) {
            sb.append("pause");
        }
    }

    private String fileName(String videoPath) {
        return StrUtil.subBefore(videoPath, ".", true);
    }

    /**
     * @param category
     * @param vedioCutoffList
     */

    public void creatFile(CategoryEnum category, List<VedioCutoff> vedioCutoffList, String dirPath) {
        VedioCutoff titles = vedioCutoffList.stream().filter(item -> CategoryEnum.TITLES.getCode().equals(item.getCategoryCode())).findFirst().orElse(null);
        VedioCutoff ending = vedioCutoffList.stream().filter(item -> CategoryEnum.ENDING.getCode().equals(item.getCategoryCode())).findFirst().orElse(null);
        List<VedioCutoff> vedioCutoffs = vedioCutoffList.stream().filter(item -> category.getCode().equals(item.getCategoryCode())).collect(Collectors.toList());
        if (CollUtil.isEmpty(vedioCutoffs)) {
            return;
        }
        for (VedioCutoff vedioCutoff : vedioCutoffs) {
            StringBuilder sb = new StringBuilder();
            if (ObjectUtil.isNotNull(vedioCutoff) && ObjectUtil.isNotNull(titles)) {
                sb.append("file '").append(CategoryEnum.TITLES.getCode()).append("_clip.ts'").append("\r\n");
            }
            sb.append("file '").append(vedioCutoff.getName()).append("_clip.ts'").append("\r\n");
            if (ObjectUtil.isNotNull(vedioCutoff) && ObjectUtil.isNotNull(ending)) {
                sb.append("file '").append(CategoryEnum.ENDING.getCode()).append("_clip.ts'");
            }
            File fileDir = new File(dirPath);
            fileDir.mkdir();
            File file = new File(fileDir + File.separator + vedioCutoff.getName() + ".txt");
            try (FileOutputStream outputStream = new FileOutputStream(file)) {
                outputStream.write(sb.toString().getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                log.error("生成txt文件异常了");
            }
        }
    }

}
